源码阅读 ARK-Runtime

Posted by RyoCY on 2025-12-28
Estimated Reading Time 13 Minutes
Words 2.7k In Total
Viewed Times

源码阅读 ARK-Runtime

NJU 2025Fall源码阅读笔记

对应项目:OpenHarmony/ark_runtime_core

panda:CLI工具,用于执行方舟字节码文件(*.abc)文件

程序入口

文件路径:panda/panda.cpp 从这里开始执行。

1
2
3
4
int main(int argc, const char **argv)
{
return panda::Main(argc, argv);
}

负责解析命令行参数

文件路径:panda/panda.cpp

函数:panda::Main()

主要工作:

  • 解析命令行参数,如字节码文件路径、入口点方法名等

  • 初始化日志

  • 准备运行时选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
int Main(const int argc, const char **argv)
{
auto start_time =
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch())
.count();

BlockSignals();
Span<const char *> sp(argv, argc);
RuntimeOptions runtime_options(sp[0]); // 解析命令行参数(文件路径、入口点等)
base_options::Options base_options(sp[0]); // 解析日志配置

panda::PandArg<bool> help("help", false, "Print this message and exit"); // 帮助信息
panda::PandArg<bool> options("options", false, "Print compiler and runtime options"); // 打印编译和运行时选项
// Tail arguments
panda::PandArg<std::string> file("file", "", "path to pandafile"); // 文件路径
panda::PandArg<std::string> entrypoint("entrypoint", "", "full name of entrypoint function or method"); // 入口点函数或方法
panda::PandArgParser pa_parser; // 参数解析器

runtime_options.AddOptions(&pa_parser); // 添加运行时选项
base_options.AddOptions(&pa_parser); // 添加日志配置

pa_parser.Add(&help); // 添加帮助信息
pa_parser.Add(&options); // 添加编译和运行时选项
pa_parser.PushBackTail(&file); // 添加文件路径
pa_parser.PushBackTail(&entrypoint); // 添加入口点函数或方法
pa_parser.EnableTail(); // 启用尾参数
pa_parser.EnableRemainder(); // 启用剩余参数

if (!pa_parser.Parse(argc, argv) || file.GetValue().empty() || entrypoint.GetValue().empty() || help.GetValue()) { // 检查参数
std::cerr << pa_parser.GetErrorString() << std::endl;
std::cerr << "Usage: "
<< "panda"
<< " [OPTIONS] [file] [entrypoint] -- [arguments]" << std::endl;
std::cerr << std::endl;
std::cerr << "optional arguments:" << std::endl;
std::cerr << pa_parser.GetHelpString() << std::endl;
return 1;
}

Logger::Initialize(base_options); // 初始化日志

arg_list_t arguments = pa_parser.GetRemainder();

if (runtime_options.IsStartupTime()) { // 打印启动时间
std::cout << "\n"
<< "Startup start time: " << start_time << std::endl;
}

auto runtime_options_err = runtime_options.Validate();
if (runtime_options_err) {
std::cerr << "Error: " << runtime_options_err.value().GetMessage() << std::endl;
return 1;
}

auto boot_panda_files = runtime_options.GetBootPandaFiles(); // 获取启动文件

if (runtime_options.GetPandaFiles().empty()) {
boot_panda_files.push_back(file.GetValue());
} else {
auto panda_files = runtime_options.GetPandaFiles();
auto found_iter = std::find_if(panda_files.begin(), panda_files.end(),
[&](auto &file_name) { return file_name == file.GetValue(); });
if (found_iter == panda_files.end()) {
panda_files.push_back(file.GetValue());
runtime_options.SetPandaFiles(panda_files);
}
}

runtime_options.SetBootPandaFiles(boot_panda_files); // 设置启动文件

if (!Runtime::Create(runtime_options)) { // 创建运行时 --runtime/runtime.cpp
std::cerr << "Error: cannot create runtime" << std::endl;
return -1;
}

// ...

创建运行时实例

文件路径:runtime/runtime.cpp

函数:Runtime::Create()

主要工作:

  • 初始化内存管理器

  • 创建 Runtime 单例

  • 调用 Initialize() 完成初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
bool Runtime::Create(const RuntimeOptions &options, const std::vector<LanguageContextBase *> &ctxs)
{
if (instance != nullptr) {
return false;
}

trace::ScopedTrace scoped_trace("Runtime::Create");
// 初始化内存配置
panda::mem::MemConfig::Initialize(options.GetHeapSizeLimit(), options.GetInternalMemorySizeLimit(),
options.GetCompilerMemorySizeLimit(), options.GetCodeCacheSizeLimit());
PoolManager::Initialize();

// 创建内部分配器
mem::InternalAllocatorPtr internal_allocator =
RuntimeInternalAllocator::Create(options.UseMallocForInternalAllocations());

BlockSignals();

CreateDfxController(options); // 创建Dfx控制器

CreateInstance(options, internal_allocator, ctxs); // 创建运行时实例

if (instance == nullptr) {
LOG(ERROR, RUNTIME) << "Failed to create runtime instance";
return false;
}

if (!instance->Initialize()) { // 初始化运行时 --runtime/runtime.cpp Runtime::Initialize()
LOG(ERROR, RUNTIME) << "Failed to initialize runtime";
delete instance;
instance = nullptr;
return false;
}

instance->GetPandaVM()->StartGC(); // 启动垃圾回收

auto *thread = ManagedThread::GetCurrent();
instance->GetNotificationManager()->VmStartEvent();
instance->GetNotificationManager()->VmInitializationEvent(thread->GetId());
instance->GetNotificationManager()->ThreadStartEvent(thread->GetId());

return true;

初始化运行时

文件路径:runtime/runtime.cpp

函数:Runtime::Initialize()

主要工作:

  • 创建 PandaVM

  • 初始化类链接器

  • 加载启动字节码文件(如标准库)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

bool Runtime::Initialize()
{
trace::ScopedTrace scoped_trace("Runtime::Initialize");

if (!CheckOptionsConsistency()) {
return false;
}

if (!LoadVerificationConfig()) { // 加载验证配置
return false;
}

auto runtime_type = options_.GetRuntimeType();
if (!CreatePandaVM(runtime_type)) { // 创建PandaVM(虚拟机核心) --runtime/panda_vm.cpp
return false;
}

if (!InitializePandaVM()) { // 初始化PandaVM --runtime/panda_vm.cpp
return false;
}

ManagedThread *thread = ManagedThread::GetCurrent();
class_linker_->InitializeRoots(thread); // 初始化类加载器 --runtime/class_linker.cpp
auto ext = GetClassLinker()->GetExtension(GetLanguageContext(runtime_type));
if (ext != nullptr) {
thread->SetStringClassPtr(ext->GetClassRoot(ClassRoot::STRING));
}

fingerPrint_ = ConvertToString(options_.GetFingerprint());

SetPandaPath();

if (!panda_vm_->InitializeFinish()) {
LOG(ERROR, RUNTIME) << "Failed to finish panda vm initialization";
return false;
}

is_initialized_ = true;
return true;

创建 PandaVM 并加载启动文件

文件路径:runtime/runtime.cpp

函数:Runtime::CreatePandaVM()

主要工作:

  • 创建虚拟机核心

  • 加载启动字节码文件(如 pandastdlib.abc)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

bool Runtime::CreatePandaVM(std::string_view runtime_type)
{
if (!ManagedThread::Initialize()) { // 初始化管理线程 --runtime/managed_thread.cpp
LOG(ERROR, RUNTIME) << "Failed to initialize managed thread";
return false;
}

panda_vm_ = PandaVM::Create(this, options_, runtime_type); // 创建PandaVM
if (panda_vm_ == nullptr) {
LOG(ERROR, RUNTIME) << "Failed to create panda vm";
return false;
}

panda_file::File::OpenMode open_mode = panda_file::File::READ_ONLY;
if (Runtime::GetOptions().GetRuntimeType() == "ecmascript") {
// In case of JS vm open a panda file for reading / writing
// because EcmaVM patches bytecode in-place
open_mode = panda_file::File::READ_WRITE;
}
// 加载启动文件(如标准库)
bool load_boot_panda_files_is_failed = options_.ShouldLoadBootPandaFiles() && !LoadBootPandaFiles(open_mode);
if (load_boot_panda_files_is_failed) {
LOG(ERROR, RUNTIME) << "Failed to load boot panda files";
return false;
}

notification_manager_->SetRendezvous(panda_vm_->GetRendezvous());

若启用验证,加载字节码文件流程

文件路径:panda/panda.cpp (返回Main)

主要工作:

  • 验证字节码正确性(可选)

  • 验证通过后继续执行

1
2
3
4
5
6
7
8
9
10
if (verif_opts.Enable) { 
// 遍历启动文件 --runtime/class_linker.cpp
runtime.GetClassLinker()->EnumerateBootPandaFiles([](const panda_file::File &pf) {
verifier::JobQueue::GetCache().FastAPI().ProcessFile(&pf);
return true;
});
// 验证文件 --runtime/verifier.cpp VerifierProcessFile()
bool result = VerifierProcessFile(verif_opts, file_name, entry);
if (!result && !verif_opts.Mode.VerifierDoesNotFail) {
ret = -1;

执行字节码文件

文件路径:panda/panda.cpp

函数:panda::Main() → Runtime::ExecutePandaFile()

调用 Runtime::ExecutePandaFile() 执行。

1
2
3
4
5
6
7
8
9
}

if (ret == 0 && (!verif_opts.Enable || !verif_opts.Mode.OnlyVerify)) {
auto res = runtime.ExecutePandaFile(file_name, entry, arguments);
if (!res) {
std::cerr << "Cannot execute panda file '" << file_name << "' with entry '" << entry << "'" << std::endl;
ret = -1;
} else {
ret = res.Value();

加载应用字节码文件

文件路径:runtime/runtime.cpp

函数:Runtime::ExecutePandaFile()

主要工作:

  • 为应用字节码创建独立的类链接上下文

  • 调用 Execute() 执行入口点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
}

Expected<int, Runtime::Error> Runtime::ExecutePandaFile(std::string_view filename, std::string_view entry_point,
const std::vector<std::string> &args)
{
if (options_.IsDistributedProfiling()) {
// Create app name from path to executable file.
std::string_view app_name = [](std::string_view path) -> std::string_view {
auto pos = path.find_last_of('/');
return path.substr((pos == std::string_view::npos) ? 0 : (pos + 1));
}(filename);
StartDProfiler(app_name);
}
// 创建应用类加载器上下文
auto ctx_err = CreateApplicationClassLinkerContext(filename, entry_point);
if (ctx_err) {
return Unexpected(ctx_err.value());
}

return Execute(entry_point, args);
}

加载 .abc 文件到内存

文件路径:runtime/file_manager.cpp

函数:FileManager::LoadAbcFile()

主要工作:

  • 从磁盘读取 .abc 文件

  • 解析文件结构(类、方法、字节码等)

  • 添加到类链接器,供后续使用

相关文件:

  • libpandafile/file.cpp - 实际打开和解析 .abc 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
bool FileManager::LoadAbcFile(const PandaString &location, panda_file::File::OpenMode open_mode)
{
auto pf = panda_file::OpenPandaFile(location, "", open_mode); // 打开Panda文件
if (pf == nullptr) {
LOG(ERROR, PANDAFILE) << "Load panda file failed: " << location;
return false;
}
auto runtime = Runtime::GetCurrent();
runtime->GetClassLinker()->AddPandaFile(std::move(pf)); // 添加Panda文件 --runtime/class_linker.cpp
if (Runtime::GetOptions().IsEnableAn()) {
auto an_location = FileManager::ResolveAnFilePath(location);
auto res = FileManager::LoadAnFile(an_location);
if (res && res.Value()) {
LOG(INFO, PANDAFILE) << "Found .an file for '" << location << "': '" << an_location << "'";
} else if (!res) {
LOG(INFO, PANDAFILE) << "Failed to load AOT file: '" << an_location << "': " << res.Error();
} else {
LOG(INFO, PANDAFILE) << "Failed to load '" << an_location << "' with unknown reason";
}
}

return true;
}

解析入口点方法

文件路径:runtime/runtime.cpp

函数:Runtime::Execute() → Runtime::ResolveEntryPoint()

ResolveEntryPoint() 解析入口点:

  • 解析类名和方法名(如 “MyClass::main”)

  • 通过类链接器获取类:class_linker_->GetClass()

  • 查找方法:cls->GetDirectMethod()

  • 返回 Method* 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
Expected<int, Runtime::Error> Runtime::Execute(std::string_view entry_point, const std::vector<std::string> &args)
{
auto resolve_res = ResolveEntryPoint(entry_point); // 解析入口点
if (!resolve_res) {
return Unexpected(resolve_res.Error());
}

NotifyAboutLoadedModules();

Method *method = resolve_res.Value();

return panda_vm_->InvokeEntrypoint(method, args); // 调用入口点
}

虚拟机调用入口点

文件路径:runtime/panda_vm.cpp

函数:PandaVM::InvokeEntrypoint()

主要工作:

  • 验证入口点方法签名

  • 调用 InvokeEntrypointImpl() 执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Expected<int, Runtime::Error> PandaVM::InvokeEntrypoint(Method *entrypoint, const std::vector<std::string> &args)
{
if (!CheckEntrypointSignature(entrypoint)) {
LOG(ERROR, RUNTIME) << "Method '" << entrypoint << "' has invalid signature";
return Unexpected(Runtime::Error::INVALID_ENTRY_POINT);
}
// 调用入口点实现 --runtime/core/core_vm.cpp
Expected<int, Runtime::Error> ret = InvokeEntrypointImpl(entrypoint, args);

ManagedThread *thread = ManagedThread::GetCurrent();
if (thread->HasPendingException()) {
auto *exception = thread->GetException();
HandleUncaughtException(exception);
ret = EXIT_FAILURE;
}

return ret;
}

实际调用方法

文件路径:runtime/core/core_vm.cpp

函数:PandaCoreVM::InvokeEntrypointImpl()

主要工作:

  • 初始化入口点所在的类

  • 准备方法参数

  • 调用 Method::Invoke()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Expected<int, Runtime::Error> PandaCoreVM::InvokeEntrypointImpl(Method *entrypoint,
const std::vector<std::string> &args)
{
Runtime *runtime = Runtime::GetCurrent();
MTManagedThread *thread = MTManagedThread::GetCurrent();
LanguageContext ctx = runtime->GetLanguageContext(*entrypoint);
ASSERT(ctx.GetLanguage() == panda_file::SourceLang::PANDA_ASSEMBLY);

ScopedManagedCodeThread sj(thread);
ClassLinker *class_linker = runtime->GetClassLinker();
if (!class_linker->InitializeClass(thread, entrypoint->GetClass())) { // 初始化类 --runtime/class_linker.cpp
LOG(ERROR, RUNTIME) << "Cannot initialize class '" << entrypoint->GetClass()->GetName() << "'";
return Unexpected(Runtime::Error::CLASS_NOT_INITIALIZED);
}

// 创建参数
ObjectHeader *object_header = nullptr;
if (entrypoint->GetNumArgs() == 1) {
coretypes::Array *arg_array = CreateArgumentsArray(args, ctx, runtime_->GetClassLinker(), thread->GetVM());
object_header = arg_array;
}

[[maybe_unused]] HandleScope<ObjectHeader *> scope(thread);
VMHandle<ObjectHeader> args_handle(thread, object_header);
Value arg_val(args_handle.GetPtr());
// 调用
Value v = entrypoint->Invoke(thread, &arg_val);

return v.GetAs<int>();
}

创建调用帧并进入解释器

文件路径:runtime/method.cpp

函数:Method::Invoke()

  • 创建方法调用帧

  • 设置参数到帧的寄存器

  • 调用解释器入口

相关文件:

  • runtime/method.cpp - Method::Invoke()

  • runtime/entrypoints/entrypoints.cpp

解释器执行字节码

文件路径:runtime/entrypoints/entrypoints.cpp

函数:InterpreterEntryPoint()

主要工作:

  • 获取方法的字节码指令

  • 调用解释器执行字节码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
extern "C" NO_ADDRESS_SANITIZE void InterpreterEntryPoint(Method *method, Frame *frame)
{
// 获取指令
auto pc = method->GetInstructions();
Method *callee = frame->GetMethod();
ASSERT(callee != nullptr);

if (callee->IsAbstract()) {
ASSERT(pc == nullptr);
panda::ThrowAbstractMethodError(callee);
HandlePendingException();
UNREACHABLE();
}

// 设置当前帧
ManagedThread *thread = ManagedThread::GetCurrent();
Frame *prev_frame = thread->GetCurrentFrame();
thread->SetCurrentFrame(frame);

auto is_compiled_code = thread->IsCurrentFrameCompiled();
thread->SetCurrentFrameIsCompiled(false);

// 执行 --runtime/interpreter/interpreter.cpp Execute()
interpreter::Execute(thread, pc, frame);
thread->SetCurrentFrameIsCompiled(is_compiled_code);

if (prev_frame != nullptr && reinterpret_cast<uintptr_t>(prev_frame->GetMethod()) == COMPILED_CODE_TO_INTERPRETER) {
thread->SetCurrentFrame(prev_frame->GetPrevFrame());
} else {
thread->SetCurrentFrame(prev_frame);
}
}

解释器主循环执行

文件路径:runtime/interpreter/interpreter.cpp

函数:interpreter::Execute()

主要工作:

  • 读取字节码指令

  • 通过 Dispatch Table(分发表)跳转到对应处理函数

  • 执行指令(如加载变量、运算、调用方法等)

  • 更新程序计数器(PC),继续下一条指令

  • 循环执行,直到方法返回

相关文件:

  • runtime/interpreter/interpreter_impl.cpp - 解释器实现

  • runtime/interpreter/interpreter-inl.h - 解释器内联实现

1
2
3
4
5
void Execute(ManagedThread *thread, const uint8_t *pc, Frame *frame, bool jump_to_eh)
{
ExecuteImpl(thread, pc, frame, jump_to_eh);
RESTORE_GLOBAL_REGS();
}

清理和退出

文件路径:panda/panda.cpp

函数:panda::Main()

主要工作:

  • 销毁运行时实例

  • 清理资源

  • 返回执行结果

1
2
3
4
if (!Runtime::Destroy()) {
std::cerr << "Error: cannot destroy runtime" << std::endl;
return -1;
}

结构图

结构图